package com.roamer.audition.web.common;

import cn.hutool.json.JSONUtil;
import com.roamer.rest.RestResult;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * 响应体返回之前做一些处理
 * <p>统一返回参数处理</p>
 *
 * @author roamer
 * @version V1.0
 * @date 2019/8/24 9:06 下午
 */
@Order(1)
@ControllerAdvice(basePackages = "com.roamer.audition.web.controller")
public class ResponseBodyWrapperAdvice implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 方法未标注 @NoRestResult 注解，并且返回类型 非ResultResponse 类型
        if (!returnType.hasMethodAnnotation(NoRestResult.class)) {
            Type type = returnType.getGenericParameterType();
            // 参数化类型处理
            if (type instanceof ParameterizedType) {
                return !RestResult.class.equals(((ParameterizedType) type).getRawType());
            }
            return !RestResult.class.equals(type);
        }
        return false;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        if (body instanceof String) {
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8);
            return JSONUtil.toJsonStr(RestResult.success(body));
        }
        return RestResult.success(body);
    }
}
